﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using MVCAppToolkit;
using NuPattern.Diagnostics;
using NuPattern.Runtime;
using NuPattern.Runtime.ToolkitInterface;

namespace SearchFormToolkit.Automation.TypeConverters
{
    /// <summary>
    /// A custom type converter for returning a list of System.String values.
    /// </summary>
    [DisplayName("Data Field Type Converter")]
    [Category("MVC Search Form Applications")]
    [Description("Returns a list of the configured Fields in the configured View Models in the form.")]
    [CLSCompliant(false)]
    public class DataFieldTypeConverter : StringConverter
    {
        private static readonly ITracer tracer = Tracer.Get<DataFieldTypeConverter>();

        /// <summary>
        /// Determines whether this converter supports standard values.
        /// </summary>
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        /// <summary>
        /// Determines whether this converter only allows selection of items returned by <see cref="GetStandardValues"/>.
        /// </summary>
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }

        /// <summary>
        /// Returns the list of string values for the enumeration
        /// </summary>
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            var items = new List<string>();

            // Get the current element the converter is configured upon
            var currentElement = context.Instance as IProductElement;
            if (currentElement != null)
            {
                // Get the search provider for the search form
                var searchProvider = GetSearchProviderFromCurrentElement(currentElement);
                if (searchProvider != null)
                {
                    // Get the configured ViewModel for the search provider
                    if (!string.IsNullOrEmpty(searchProvider.ViewModel))
                    {
                        var viewModel = searchProvider.AsElement().Root.As<IMvcApplication>().DefaultView.ViewModels.ViewModel
                            .FirstOrDefault(vm => vm.CodeIdentifier.Equals(searchProvider.ViewModel, StringComparison.OrdinalIgnoreCase));
                        if (viewModel != null)
                        {
                            // Add the currently configured fields from the configured ViewModel
                            foreach (var field in viewModel.Fields.Field)
                            {
                                items.Add(field.CodeIdentifier);
                            }
                        }
                    }
                }
            }

            return new StandardValuesCollection(items);
        }

        private ISearchProvider GetSearchProviderFromCurrentElement(IProductElement currentElement)
        {
            // Is this configured on a result column?
            if (currentElement.Parent.DefinitionName.Equals(typeof(Columns).Name, StringComparison.OrdinalIgnoreCase))
            {
                return currentElement.Parent.As<IColumns>().Parent.Parent.SearchProvider;
            }
            else
            {
                // Is this configured on a search criterion?
                if (currentElement.Parent.DefinitionName.Equals(typeof(SearchCriteria).Name, StringComparison.OrdinalIgnoreCase))
                {
                    return currentElement.Parent.As<ISearchCriteria>().Parent.SearchProvider;
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }
}
